package inventory.shiro.realm;

import inventory.common.UserStatusEnum;
import inventory.entity.Manager;
import inventory.mappers.ManagerMapper;
import org.apache.shiro.authc.*;
import org.apache.shiro.realm.AuthenticatingRealm;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;

import java.util.Date;


public class ManagerRealm extends AuthenticatingRealm {

    @Autowired
    private ApplicationContext applicationContext;


    //认证，subject.login()的时候会进去该方法
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {

        System.out.println("进入自定义managerRealm认证...");

        //获取用户名密码,即在subject.login(token)中token的值

        Manager tempManager = new Manager();
        tempManager.setWorkId((String) token.getPrincipal());//token.getPrincipal()
        String password = new String((char[]) token.getCredentials());  //token.getCredentials()

        System.out.println("manager的workId:"+tempManager.getWorkId());
        System.out.println("manager的password:"+password);

        //从applicationContext中拿到managerMapper
        ManagerMapper managerMapper = (ManagerMapper) applicationContext.getBean("managerMapper");

        //查询是否有对应用户
        Manager checkManager = managerMapper.selectOne(tempManager);
        if (checkManager==null){
            throw new UnknownAccountException(tempManager.getWorkId());
        }

        //---------检查账户的管理员是否过期------
        Date timeLimit = checkManager.getTimeLimit();
        Date now = new Date();
        //如果现在的时间在时限之后，则不允许登录
        if (now.after(timeLimit)){
            throw new ExpiredCredentialsException("账号已到期");
        }
        if (checkManager.getStatus().equals(UserStatusEnum.LOCK.getCode())){
            throw new LockedAccountException("管理员账号被封");
        }

        //交给AuthenticationRealm使用CredentialsMatcher进行密码匹配
        SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
                checkManager, //认证过后的安全用户对象，包含了该用户所有信息
                //下面的参数才是真正拿去做密码比对的，上面的checkManager就存入了subject，方便其他方法调用
                checkManager.getPassword(), //密码
                ByteSource.Util.bytes(checkManager.getSalt()), //salt
                getName() //realm name
        );
        return authenticationInfo;

    }
}
